package com.xyht.medicine_management_system.modules.kuaidi.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.google.gson.Gson;
import com.kuaidi100.sdk.response.SubscribePushParamResp;
import com.kuaidi100.sdk.response.SubscribePushResult;
import com.kuaidi100.sdk.utils.SignUtils;
import com.xyht.medicine_management_system.common.commonReturn.CommonCodeEnum;
import com.xyht.medicine_management_system.common.commonReturn.CommonResult;
import com.xyht.medicine_management_system.common.commonReturn.ResponseResult;
import com.xyht.medicine_management_system.common.util.TimeUtil;
import com.xyht.medicine_management_system.modules.addresses.entity.MmsAddresses;
import com.xyht.medicine_management_system.modules.kuaidi.constant.KuaiDi100ConfigConstant;
import com.xyht.medicine_management_system.modules.kuaidi.entity.*;
import com.xyht.medicine_management_system.modules.kuaidi.entity.req.MmsKuaidiInfoBatchReq;
import com.xyht.medicine_management_system.modules.kuaidi.entity.req.MmsKuaidiInfoReq;
import com.xyht.medicine_management_system.modules.kuaidi.entity.resp.*;
import com.xyht.medicine_management_system.modules.kuaidi.mapper.MmsKuaidiCompanyMapper;
import com.xyht.medicine_management_system.modules.kuaidi.mapper.MmsKuaidiInfoMapper;
import com.xyht.medicine_management_system.modules.kuaidi.mapper.MmsKuaidiSettingMapper;
import com.xyht.medicine_management_system.modules.kuaidi.myEnum.KuaidiStatusEnum;
import com.xyht.medicine_management_system.modules.kuaidi.service.MmsKuaidiInfoService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xyht.medicine_management_system.modules.kuaidi.util.Kuaidi100Util;
import com.xyht.medicine_management_system.modules.order.entity.MmsOrder;
import com.xyht.medicine_management_system.modules.order.mapper.MmsOrderMapper;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import java.util.*;

import static com.xyht.medicine_management_system.common.util.ParamCheckUtil.isNullOrEmpty;
import static com.xyht.medicine_management_system.modules.common.constant.TaskStatus.TASK_STATUS_DONE;
import static com.xyht.medicine_management_system.modules.kuaidi.constant.IsOpenFlagConstant.IS_OPEN_FLAG_YES;
import static com.xyht.medicine_management_system.modules.order.constant.OrderConstant.*;

/**
 * <p>
 * 商家发货快递信息 服务实现类
 * </p>
 *
 * @author XYHT
 * @since 2024-07-02
 */
@Service
@Log4j2
public class MmsKuaidiInfoServiceImpl extends ServiceImpl<MmsKuaidiInfoMapper, MmsKuaidiInfo> implements MmsKuaidiInfoService {
    @Resource
    private MmsKuaidiInfoMapper mmsKuaidiInfoMapper;
    @Resource
    private MmsKuaidiSettingMapper mmsKuaidiSettingMapper;
    @Resource
    private MmsKuaidiCompanyMapper mmsKuaidiCompanyMapper;
    @Resource
    private MmsOrderMapper mmOrderMapper;
    @Resource
    private PlatformTransactionManager transactionManager;
    @Resource
    private Kuaidi100Util kuaidi100Util;
    @Resource
    private KuaiDi100ConfigConstant kuaiDi100ConfigConstant;

    @Override
    public ResponseResult BatchSendKuaidi(MmsKuaidiInfoBatchReq batchReq) {
        if (isNullOrEmpty(batchReq.getOrderIdList(), batchReq.getKuaidiCompany())) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }

        if (batchReq.getOrderIdList().size() < 1) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }

        //校验发货信息是否配置
        List<MmsKuaidiSetting> kuaidiSettingList = mmsKuaidiSettingMapper.selectList(new LambdaQueryWrapper<MmsKuaidiSetting>()
                .eq(MmsKuaidiSetting::getIsOpen, IS_OPEN_FLAG_YES));
        if (kuaidiSettingList == null || kuaidiSettingList.size() < 1) {
            return CommonResult.failed(CommonCodeEnum.KUAIDI_SETTING_NOT_EXIST);
        }
        MmsKuaidiSetting kuaidiSetting = kuaidiSettingList.get(0);

        //校验快递公司是否存在
        List<MmsKuaidiCompany> kuaidiCompanyList = mmsKuaidiCompanyMapper.selectList(new LambdaQueryWrapper<MmsKuaidiCompany>()
                .eq(MmsKuaidiCompany::getComCode, batchReq.getKuaidiCompany()));
        if (kuaidiCompanyList == null || kuaidiCompanyList.size() < 1) {
            return CommonResult.failed(CommonCodeEnum.KUAIDI_COMPANY_NOT_EXIST);
        }

        //校验订单并发货
        List<Map<String,Object>> list = new ArrayList<>();
        for (String orderId : batchReq.getOrderIdList()) {
            MmsOrder order = checkOrderIsSend(orderId);
            if (order == null) {
                continue;
            }
            //开启事务
            DefaultTransactionDefinition dt = new DefaultTransactionDefinition();
            // 嵌套事务 PROPAGATION_REQUIRES_NEW 每次开启一个新的事务
            dt.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
            // 设置嵌套事务
            TransactionStatus status = transactionManager.getTransaction(dt);

            try {
                MmsAddresses addresses = JSONObject.parseObject(order.getAddressInfo(), MmsAddresses.class);

                MmsKuaidiInfo addKuaidiInfo = new MmsKuaidiInfo();
                addKuaidiInfo.setSendAddr(kuaidiSetting.getSendAddr());
                addKuaidiInfo.setSendTel(kuaidiSetting.getSendTel());
                addKuaidiInfo.setSendName(kuaidiSetting.getSendName());
                addKuaidiInfo.setKuaidiCompany(batchReq.getKuaidiCompany());
                addKuaidiInfo.setKuaidiGoodsName("药品");
                addKuaidiInfo.setRecAddr(addresses.getAddressDetail());
                addKuaidiInfo.setRecTel(addresses.getPhone());
                addKuaidiInfo.setRecName(addresses.getReceiver());
                addKuaidiInfo.setRemark(batchReq.getRemark());
                addKuaidiInfo.setOrderId(orderId);

                //创建快递订单
                KuaidiSendResultResp sendResp = kuaidi100Util.kuaidiSend(addKuaidiInfo,list);
                if (sendResp == null) {
                    log.debug("异常回滚了+++++++++++++1111111");
                    transactionManager.rollback(status);
                    continue;
                }
                addKuaidiInfo.setKuaidiNum(sendResp.getData().getKuaidinum());
                addKuaidiInfo.setKuaidiOrderId(sendResp.getData().getOrderId());
                addKuaidiInfo.setKuaidiTaskId(sendResp.getData().getTaskId());
                addKuaidiInfo.setKuaidiStatus(KuaidiStatusEnum.ORDER_SUCCESS.getCode());
                mmsKuaidiInfoMapper.insert(addKuaidiInfo);

                MmsOrder updateOrder = new MmsOrder();
                updateOrder.setId(orderId);
                updateOrder.setCarrierInfo(addKuaidiInfo.getId());
                updateOrder.setOrderStatus(ORDER_STATUS_TO_BE_RECEIVED);
                mmOrderMapper.updateById(updateOrder);

                packageResult(list, orderId, "成功",true);
                transactionManager.commit(status);
            } catch (Exception e) {
                log.debug("异常回滚了+++++++++++++22222222");
                packageResult(list, orderId, "程序异常",false);
                transactionManager.rollback(status);
            } finally {
                if (status.isNewTransaction() && !status.isCompleted()) {
                    transactionManager.commit(status);
                }
            }
        }
        return CommonResult.success(list);
    }

    private void packageResult(List<Map<String, Object>> list, String orderId, String msg,boolean isSuccess) {
        HashMap<String, Object> map = new HashMap<>();
        map.put("msg", msg);
        map.put("orderId", orderId);
        map.put("result", isSuccess);
        list.add(map);
    }

    private MmsOrder checkOrderIsSend(String orderId) {
        MmsOrder order = mmOrderMapper.selectById(orderId);
        if (order == null) {
            return null;
        }
        if (!order.getOrderStatus().equals(ORDER_STATUS_TO_BE_DELIVERED)) {
            return null;
        }
        return order;
    }

    /**
     * @description 取消快递订单  清除CarrierInfo
     * @create 2024/7/3
     * @author dxn
     */
    @Override
    public ResponseResult cancelKuaidi(MmsKuaidiInfoReq req) {
        if (isNullOrEmpty(req.getOrderId())) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }
        MmsOrder orderInfo = mmOrderMapper.selectById(req.getOrderId());
        if (orderInfo == null){
            return CommonResult.failed(CommonCodeEnum.ORDER_NOT_EXIST);
        }

        MmsKuaidiInfo kuaidiInfo = mmsKuaidiInfoMapper.selectById(orderInfo.getCarrierInfo());
        if (kuaidiInfo == null) {
            return CommonResult.failed(CommonCodeEnum.KUAIDI_NOT_EXIST);
        }
        KuaidiCancelResp kuaidiCancelResp = kuaidi100Util.kuaidiCancel(kuaidiInfo);
        if (kuaidiCancelResp.getResult()) {
            MmsOrder order = new MmsOrder();
            order.setId(req.getOrderId());
            order.setCarrierInfo("");
            mmOrderMapper.updateById(order);
        }
        return CommonResult.success(kuaidiCancelResp);
    }

    @Override
    public ResponseResult getKuaidiTrackInfo(MmsKuaidiInfoReq req) {
        if (isNullOrEmpty(req.getOrderId())) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }
        MmsOrder order = mmOrderMapper.selectById(req.getOrderId());
        if (order == null) {
            return CommonResult.failed(CommonCodeEnum.ORDER_NOT_EXIST);
        }

        if (isNullOrEmpty(order.getCarrierInfo())) {
            return CommonResult.failed(CommonCodeEnum.KUAIDI_NOT_EXIST);
        }

        MmsKuaidiInfo kuaidiInfo = mmsKuaidiInfoMapper.selectById(order.getCarrierInfo());
        if (kuaidiInfo == null) {
            return CommonResult.failed(CommonCodeEnum.KUAIDI_NOT_EXIST);
        }

        Date queryDate = kuaidiInfo.getKuaidiTrackQueryTime();
        Date nowDate = new Date();
        List<KuaiDiQueryResp> trackInfo;
        if (isNullOrEmpty(queryDate)
                || TimeUtil.calculatetimeGapMinute(queryDate, nowDate) > 35) {
            //查询快递轨迹信息
            trackInfo = kuaidi100Util.queryTrack(kuaidiInfo);
            if (trackInfo != null){
                MmsKuaidiInfo updateKuaidiInfo = new MmsKuaidiInfo();
                updateKuaidiInfo.setId(kuaidiInfo.getId());
                updateKuaidiInfo.setKuaidiTrackQueryTime(nowDate);
                updateKuaidiInfo.setKuaidiTrack(JSONObject.toJSONString(trackInfo));
                mmsKuaidiInfoMapper.updateById(updateKuaidiInfo);
            }
            return CommonResult.success(trackInfo);
        }
        trackInfo = JSONObject.parseArray(kuaidiInfo.getKuaidiTrack(), KuaiDiQueryResp.class);
        return CommonResult.success(trackInfo);
    }

    @Override
    public ResponseResult getKuaidiInfo(MmsKuaidiInfoReq req) {
        if (isNullOrEmpty(req.getOrderId())) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }
        MmsOrder order = mmOrderMapper.selectById(req.getOrderId());
        if (order == null) {
            return CommonResult.failed(CommonCodeEnum.ORDER_NOT_EXIST);
        }

        if (isNullOrEmpty(order.getCarrierInfo())) {
            return CommonResult.failed(CommonCodeEnum.KUAIDI_NOT_EXIST);
        }

        MmsKuaidiInfo kuaidiInfo = mmsKuaidiInfoMapper.selectById(order.getCarrierInfo());
        if (kuaidiInfo == null) {
            return CommonResult.failed(CommonCodeEnum.KUAIDI_NOT_EXIST);
        }

        if (kuaidiInfo == null) {
            return CommonResult.failed(CommonCodeEnum.KUAIDI_NOT_EXIST);
        }

        Date queryDate = kuaidiInfo.getKuaidiTrackQueryTime();
        Date nowDate = new Date();
        List<KuaiDiQueryResp> trackInfo;
        if (isNullOrEmpty(queryDate)
                || TimeUtil.calculatetimeGapMinute(queryDate, nowDate) > 35) {
            //查询快递轨迹信息
            trackInfo = kuaidi100Util.queryTrack(kuaidiInfo);

            if (trackInfo != null){
                MmsKuaidiInfo updateKuaidiInfo = new MmsKuaidiInfo();
                updateKuaidiInfo.setId(kuaidiInfo.getId());
                updateKuaidiInfo.setKuaidiTrackQueryTime(nowDate);
                updateKuaidiInfo.setKuaidiTrack(JSONObject.toJSONString(trackInfo));
                mmsKuaidiInfoMapper.updateById(updateKuaidiInfo);
            }
        }else{
            trackInfo = JSONObject.parseArray(kuaidiInfo.getKuaidiTrack(), KuaiDiQueryResp.class);
        }

        MmsKuaidiInfoResp resp = new MmsKuaidiInfoResp();
        BeanUtils.copyProperties(kuaidiInfo, resp);
        resp.setKuaidiTrack(JSONObject.toJSONString(trackInfo));

        List<MmsKuaidiCompany> kuaidiCompanyList = mmsKuaidiCompanyMapper.selectList(new LambdaQueryWrapper<MmsKuaidiCompany>()
                .eq(MmsKuaidiCompany::getComCode, kuaidiInfo.getKuaidiCompany()));
        if (kuaidiCompanyList != null && kuaidiCompanyList.size() > 0) {
            resp.setKuaidiCompanyName(kuaidiCompanyList.get(0).getComName());
        }
        return CommonResult.success(resp);
    }

    @Override
    public ResponseResult printKuaidiInfo(MmsKuaidiInfoBatchReq req) {
        if (isNullOrEmpty(req.getOrderIdList())) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }

        if (req.getOrderIdList().size() < 1){
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }

        List<String> pringImgList = new ArrayList<>();
        for (String orderId : req.getOrderIdList()){
            MmsOrder order = mmOrderMapper.selectById(orderId);
            if (order == null) {
                return CommonResult.failed(CommonCodeEnum.ORDER_NOT_EXIST);
            }

            if (isNullOrEmpty(order.getCarrierInfo())) {
                return CommonResult.failed(CommonCodeEnum.KUAIDI_NOT_EXIST);
            }

            MmsKuaidiInfo kuaidiInfo = mmsKuaidiInfoMapper.selectById(order.getCarrierInfo());
            if (kuaidiInfo == null) {
                return CommonResult.failed(CommonCodeEnum.KUAIDI_NOT_EXIST);
            }
            String resultPrintImg = "";
            if (isNullOrEmpty(kuaidiInfo.getPrintImg())) {
                KuaiDiPrintResp printImg = kuaidi100Util.customTemplate(kuaidiInfo);
                if (isNullOrEmpty(printImg)) {
                    return CommonResult.failed(CommonCodeEnum.KUAIDI_PRINT_ORDER_FAIL);
                }

                MmsKuaidiInfo updateKuaidiInfo = new MmsKuaidiInfo();
                updateKuaidiInfo.setId(kuaidiInfo.getId());
                updateKuaidiInfo.setPrintImg(printImg.getLabel());
                updateKuaidiInfo.setPrintTaskId(printImg.getTaskId());
                mmsKuaidiInfoMapper.updateById(updateKuaidiInfo);

                resultPrintImg = printImg.getLabel();
            } else {
                resultPrintImg = kuaidiInfo.getPrintImg();
            }
            pringImgList.add(resultPrintImg);
        }

        return CommonResult.success(pringImgList);
    }

    @Override
    public Map<String, Object> kuaidiOrderInfoCallback(HttpServletRequest request) {
        String param = request.getParameter("param");
        String sign = request.getParameter("sign");
        //校验签名
        String signStr = param + kuaiDi100ConfigConstant.getSALT();
        String ourSign = SignUtils.sign(signStr);
        if (!ourSign.equals(sign)) {
            log.debug("签名校验失败+++++++++++++");
            return responseFail("签名校验失败");
        }
        KuaidiCallbackParamEntity callbackEntity = JSONObject.parseObject(param, KuaidiCallbackParamEntity.class);

        List<MmsKuaidiInfo> kuaidiInfoList = mmsKuaidiInfoMapper.selectList(new LambdaQueryWrapper<MmsKuaidiInfo>()
                .eq(MmsKuaidiInfo::getKuaidiNum, callbackEntity.getKuaidinum()));
        if (kuaidiInfoList == null || kuaidiInfoList.size() < 1) {
            return responseFail("快递信息不存在");
        }
        MmsKuaidiInfo kuaidiInfo = kuaidiInfoList.get(0);
        List<MmsOrder> orderList = mmOrderMapper.selectList(new LambdaQueryWrapper<MmsOrder>()
                .eq(MmsOrder::getCarrierInfo, kuaidiInfo.getId()));
        if (orderList == null || orderList.size() < 1) {
            return responseFail("订单信息不存在");
        }
        MmsOrder order = orderList.get(0);

        KuaidiStatusEnum kuaidiStatusEnum = KuaidiStatusEnum.fromCode(Integer.parseInt(callbackEntity.getStatus()));
        MmsOrder updateOrder = new MmsOrder();
        updateOrder.setId(order.getId());
        switch (kuaidiStatusEnum) {
            case ORDER_SUCCESS:
                break;
            case ORDER_RECEIVED:
                break;
            case ORDER_FAILED:
                break;
            case ORDER_REACTIVATED:
                break;
            case USER_CANCELLED:
                break;
            case ORDER_CANCELLED:
                break;
            case RETURNED:
                break;
            case SIGNED:
            case ABNORMAL_SIGNED:
                updateOrder.setOrderStatus(ORDER_STATUS_ALREADY_RECEIVED);
                mmOrderMapper.updateById(updateOrder);
                break;
        }

        //修改快递状态
        MmsKuaidiInfo updateKuaidiInfo = new MmsKuaidiInfo();
        updateKuaidiInfo.setId(kuaidiInfo.getId());
        updateKuaidiInfo.setKuaidiStatus(kuaidiStatusEnum.getCode());
        mmsKuaidiInfoMapper.updateById(updateKuaidiInfo);

        return responseSuccess();
    }


    @Override
    public Map<String, Object> kuaidiStatusInfoCallback(HttpServletRequest request) {
        String param = request.getParameter("param");
        String sign = request.getParameter("sign");
        //建议记录一下这个回调的内容，方便出问题后双方排查问题
        //log.debug("快递100订阅推送回调结果|{}|{}",param,sign);
        //订阅时传的salt,没有可以忽略
        String salt = "";
        String ourSign = SignUtils.sign(param + salt);
        if (!ourSign.equals(sign)) {
            log.debug("签名校验失败+++++++++++++");
            return responseFail("签名校验失败");
        }

        //业务处理
        SubscribePushParamResp subscribePushParamResp = JSON.parseObject(param, SubscribePushParamResp.class);
        SubscribePushResult lastResult = subscribePushParamResp.getLastResult();

        List<MmsKuaidiInfo> kuaidiInfoList = mmsKuaidiInfoMapper.selectList(new LambdaQueryWrapper<MmsKuaidiInfo>()
                .eq(MmsKuaidiInfo::getKuaidiNum, lastResult.getNu()));
        if (kuaidiInfoList == null || kuaidiInfoList.size() < 1) {
            return responseFail("快递信息不存在");
        }
        MmsKuaidiInfo kuaidiInfo = kuaidiInfoList.get(0);

        MmsKuaidiInfo updatedKuaidiInfo = new MmsKuaidiInfo();
        updatedKuaidiInfo.setId(kuaidiInfo.getId());
        updatedKuaidiInfo.setKuaidiTrack(JSON.toJSONString(lastResult.getData()));
        mmsKuaidiInfoMapper.updateById(updatedKuaidiInfo);
        return responseSuccess();
    }

    private Map<String, Object> responseSuccess() {
        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("result", true);
        resultMap.put("returnCode", "200");
        resultMap.put("message", "成功");
        return resultMap;
    }

    private Map<String, Object> responseFail(String message) {
        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("result", false);
        resultMap.put("returnCode", "500");
        resultMap.put("message", message);
        return resultMap;
    }

}
